#include "uhf900.h"

#define REV_STA_SOF    0x01
#define REV_STA_LEN    0x02
#define REV_STA_CMD   0x03
#define REV_STA_STA    0x04
#define REV_STA_DAT    0x05
#define REV_STA_FCS    0x06

#define UART_ADDR       _IOW(0x02,1,unsigned long)

#define _UART1_SEL_125K     0
#define _UART1_SEL_14443    1
#define _UART1_SEL_15693    2
#define _UART1_SEL_900M     3
#define _UART1_SEL_2P4G     4
#define _UART1_SEL_UART1    5

#define _UART2_SEL_LOCK     10
#define _UART2_SEL_GATE     11
#define _UART2_SEL_GATE2    12
#define _UART2_SEL_UART2    13

#define CPLD_DEV "/dev/cpld"


RfidMem_t mem;
uint8 revCmd;
bool runFlag;
int cpld_fd;

int UHF900M(){
	cpld_fd = open(CPLD_DEV,O_RDWR);
	if(cpld_fd<0) printf("Error opening %s device.", CPLD_DEV);
	uart_open(COM1_ID);	
	tty[COM1_ID].baud = B57600;
	uart_setbaud(COM1_ID);
} 

uint8 Inventory()
{
    uint8 *data = NULL;

    tty[COM1_ID].txlen = BuildReqFrame(tty[COM1_ID].txbuf, UHFCMD_INVENTORY, data, 0);
    uart_write(COM1_ID);
    revCmd = UHFCMD_INVENTORY;
 
    return ReceiveRspFrame(UHF_RSP_TIME, UHFCMD_INVENTORY);
}


uint8 InventoryStop()
{
    uint8 *data = NULL;

    tty[COM1_ID].txlen = BuildReqFrame(tty[COM1_ID].txbuf, UHFCMD_STOP_GET, data, 0);
    uart_write(COM1_ID);

    return ReceiveRspFrame(UHF_RSP_TIME, UHFCMD_STOP_GET);
}

uint8 WriteBuf(uint8 blockId, uint8 addr, uint8 *buf, uint8 len)
{
    uint8 data[9];
    len = 1;  // only support len=1

    /** data[0~3]: access password **/
    data[0] = 0x00;
    data[1] = 0x00;
    data[2] = 0x00;
    data[3] = 0x00;

    data[4] = blockId;
    data[5] = addr;
    data[6] = len;

    data[7] = buf[0];
    data[8] = buf[1];

    tty[COM1_ID].txlen = BuildReqFrame(tty[COM1_ID].txbuf, UHFCMD_SINGLE_WRITE_DATA, data, 9);
    uart_write(COM1_ID);

    return ReceiveRspFrame(UHF_RSP_TIME, UHFCMD_SINGLE_WRITE_DATA);
}

uint8 ReadBuf(uint8 blockId, uint8 addr, uint8 len)
{
    uint8 data[7];

    /** data[0~3]: access password **/
    data[0] = 0x00;
    data[1] = 0x00;
    data[2] = 0x00;
    data[3] = 0x00;

    data[4] = blockId;
    data[5] = addr;
    data[6] = len;

    tty[COM1_ID].txlen = BuildReqFrame(tty[COM1_ID].txbuf, UHFCMD_SINGLE_READ_DATA, data, 7);
    uart_write(COM1_ID);

    return ReceiveRspFrame(UHF_RSP_TIME, UHFCMD_SINGLE_READ_DATA);
}

uint8 BuildReqFrame(uint8 *pRet, uint8 cmd, uint8 *data, uint8 dataLen)
{
    uint8 frameLen = dataLen+4;  // 3 = sof(1)+len(1)+cmd(1)+fcs(1)
    pRet[0] = UHF_SOF;
    pRet[1] = dataLen+2;     // 1 = cmd(1)+fcs(1)
    pRet[2] = cmd;
    uint8 j=0;
    if(dataLen>0)
        for(uint8 i=0; i<dataLen; i++){
            if(data[i]==UHF_SOF || data[i]==UHF_EOF){
                pRet[3+i+j] = 0xFF;
                j++;
            }
            pRet[3+i+j] = data[i];
        }
    frameLen += j;
    //memcpy(pRet+3, data, dataLen);
    pRet[frameLen-1] = UHF_EOF;

    return frameLen;
}

uint8 ReceiveRspFrame(long timeout, uint8 cmd)
{
    uint8* const p = tty[COM1_ID].rxbuf;
    char buff[256];
    uint8 *data = NULL;
    uint8 ret = 0xFF, revSta = REV_STA_SOF;
    uint8 len=0, framelen=0, datalen=0, i=0, j=0;
    tty[COM1_ID].timeout = timeout;

    while(1){
        uart_read(COM1_ID);
        len = tty[COM1_ID].rxlen;
        //PrintUartRxBuf(COM1_ID);   // ==============
        if(len == 0) return ret;

        i=0;
        do{

            //qDebug("STA:%d\tp[%d]:%02X", revSta, i, p[i]);
            switch(revSta){
            case REV_STA_SOF:
                if(p[i++] == UHF_SOF)
                    revSta = REV_STA_LEN;
                break;
            case REV_STA_LEN:
                framelen = p[i]+2;  // 2=sof(1)+len(1)
                datalen = p[i]-2;  // 2=cmd(1)+fcs(1)
                data = new uint8[framelen];
                j=0;
                data[j++] = UHF_SOF;
                data[j++] = p[i++];
                revSta = REV_STA_CMD;
                break;
            case REV_STA_CMD:
                data[j++] = p[i++];
                revSta = REV_STA_DAT;
                break;
            case REV_STA_DAT:
                if((p[i]==UHF_SOF || p[i]==UHF_EOF)&&(data[j-1]==0xFF))
                    data[j-1] = p[i++];
                else
                    data[j++] = p[i++];
                /*
                if(p[i++] != 0xFF)
                    data[j++] = p[i-1];*/
                if((j-3) >= datalen)
                    revSta = REV_STA_FCS;
                break;
            case REV_STA_FCS:
                if(p[i] == UHF_EOF){
                    data[j++] = p[i++];
                    memcpy(p, data, framelen);
                    tty[COM1_ID].rxlen = framelen;
                    if(data[UHF_RPC_CMD] == cmd){
                        ret = p[UHF_RPC_STA];

                        printf("\nRxbuf_r:"); 
						for(int i=0;i<tty[COM1_ID].rxlen;i++) printf("%x ",tty[COM1_ID].rxbuf[i]);
						printf("\n");

                        return ret;
                    }
                }

                delete [] data;
                revSta = REV_STA_SOF;
                break;
            }
        }while(--len);
    }

    return ret;
}
